<script setup lang="ts">
import { watch, nextTick, onMounted, reactive, ref } from "vue";

defineOptions({
  name: "NewHoverPlay"
});
const props = defineProps({
  onChange: {
    type: Function
  },
  time: {
    type: Number,
    default: 0
  },
  index: {},
  boundary: {
    default: {
      top: 20,
      bottom: 20,
      left: 20,
      right: 20
    }
  }
});
const visible = ref(false);
const attribute = reactive({
  id: "",
  timer: null,
  time: props.time,
  boundary: props.boundary,
  transition: {
    time: 500
  }
});
watch(visible, (n, o) => {
  if (props.onChange) {
    props.onChange(props.index, n);
  }
});
const generateUUID = (): string => {
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    const r = (Math.random() * 16) | 0,
      v = c === "x" ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
};
const addHoverEvent = () => {
  const target = document.getElementById(attribute.id);
  target.addEventListener("mouseenter", mouseOver);
};
const mouseOver = (event: MouseEvent) => {
  event.target.addEventListener("mouseleave", mouseOut);
  // 开始计时
  attribute.timer = setInterval(() => {
    if (attribute.time <= 0) {
      clearInterval(attribute.timer);
      visible.value = true;
      nextTick(() => {
        showContent(attribute.id, attribute.boundary);
      });
      return;
    }
    attribute.time -= 10;
  }, 10);
};

const mouseOut = () => {
  clearInterval(attribute.timer);
  attribute.time = props.time;
  resetPosition(attribute.id);
  setTimeout(() => {
    visible.value = false;
  }, attribute.transition.time);
};

const showContent = (
  id: string,
  boundary: { top: number; bottom: number; left: number; right: number }
) => {
  const content = document.getElementById(id + "-target");
  const position = content.getBoundingClientRect();

  // 距离顶部的位置
  const top = position.top;
  // 距离左侧的位置
  const left = position.left;
  // 距离右侧的位置
  const right = window.innerWidth - position.left - position.width;
  // 距离低部的位置
  const bottom = window.innerHeight - position.top - position.height;
  // console.log(top,right,bottom,left)
  // 顶部超出
  if (top <= boundary.top) {
    content.style.top = `calc(50% - ${top - boundary.top}px)`;
  }
  // 底部超出
  if (bottom <= boundary.bottom) {
    content.style.top = `calc(50% + ${bottom - boundary.bottom}px)`;
  }
  // 左侧超出
  if (left <= boundary.left) {
    content.style.left = `calc(50% - ${left - boundary.left}px)`;
  }
  // 右侧超出
  if (right <= boundary.right) {
    content.style.left = `calc(50% + ${right - boundary.right}px)`;
  }
  content.style.opacity = "1";
};

const resetPosition = (id: string) => {
  const content = document.getElementById(id + "-target");
  if (content !== undefined && content !== null && visible.value) {
    content.style.opacity = "0";
  }
  // content.style.left = '50%'
  // content.style.top = '50%'
};
onMounted(() => {
  attribute.id = generateUUID();
  nextTick(() => {
    addHoverEvent();
  });
});
</script>

<template>
  <div :id="attribute.id" class="hover-show">
    <div class="target">
      <slot />
    </div>
    <div v-if="visible" :id="attribute.id + '-target'" class="content-wrapper">
      <slot name="content" />
    </div>
  </div>
</template>

<style scoped lang="css">
.hover-show {
  position: relative;
  display: inline-block;
}

.target {
  display: inline-block;
  height: 100%;
  width: 100%;
}

.content-wrapper {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 300ms;
  opacity: 0;
  z-index: 99;
}
</style>
